import time

from flask_restful import current_app

from ...models import StockGood, Stockdetail, StockWarehouse, Realstock
from extensions import db
# from ...tasks.sale_stock_sync import sync_all_sale_stock
from ...utils.decorators import with_session


# from stock.tasks.stock_update_task import stock_out_task
# from uuid import uuid4


@with_session
def check_committed(business_no):
    detail_record = db.session.query(Stockdetail).filter_by(wms_seq=business_no).first()
    if detail_record:
        current_app.logger.info("业务流水号{}重复提交".format(business_no))
        raise Exception("业务单号{}重复提交".format(business_no))
    return detail_record


@with_session
def stock_out(kw):
    """
    @desc: 销售出库接口，同时扣减实物库存和占用库存
    @param order_id: 订单号, 必要, 字符串
    @param warehouse_id: 仓库ID, 必要, 字符串
    @param warehouse_name: 仓库名称, 可选, 字符串
    @param sku_id: 商品编号, 必要, 字符串
    @param status_id: 商品状态类型，必要, 正整数
    @param amount: 数量，必要，正整数
    @param user_id: 操作用户，必要，字符串
    @param business_no: 业务流水号，必要，字符串
    @param business_type: 业务类型，必要，正整数
    @param order_type: 订单类型，必要，正整数
    """
    current_time = time.strftime("%Y-%m-%d %H:%M:%S")
    order_id = str(kw["order_id"])
    user_id = kw["user_id"]
    sku_id = kw["sku_id"]
    status_id = kw.get('status_id', 1)
    amount = abs(kw.get('amount', 0))
    warehouse_id = kw.get('warehouse_id')
    business_no = kw.get('business_no')
    # business_no = uuid4().hex
    business_type = kw.get('business_type')
    order_type = kw.get('order_type')

    wh = db.session.query(StockWarehouse).filter_by(warehouse_id=warehouse_id).first()
    real_stock_record = db.session.query(Realstock).filter_by(sku_id=sku_id, status_id=status_id, warehouse_id=warehouse_id).first()

    if not real_stock_record:
        raise Exception("实物库存表仓库{}不存在商品{}记录".format(warehouse_id, sku_id))
    # db.session.query(Realstock).filter_by(id=real_stock_record.id)
    check_committed(business_no)

    goods = db.session.query(StockGood).filter_by(sku_id=sku_id).first()
    if not goods:
        raise Exception("商品表不存在商品{}".format(sku_id))
    original_occupy_record = db.session.query(Stockdetail).filter_by(order_id=order_id,
                                                                     sku_id=sku_id,
                                                                     warehouse_id=warehouse_id,
                                                                     status_id=status_id,
                                                                     order_type=13,
                                                                     remark='1').first()
    # 库存流水
    new_detail_record = Stockdetail(operation_time=current_time,
                                    warehouse_id=warehouse_id,
                                    warehouse_name=wh.warehouse_name,
                                    business_type=business_type,
                                    order_type=order_type,
                                    business_no=business_no,
                                    wms_seq=business_no,
                                    order_id=order_id,
                                    status_id=status_id,
                                    sku_id=sku_id,
                                    amount=-amount,
                                    original_real_stock=real_stock_record.real_stock,
                                    original_occupy_stock=real_stock_record.occupy_stock,
                                    real_stock_balance=real_stock_record.real_stock - amount,
                                    occupy_stock_balance=real_stock_record.occupy_stock - occupy_amount,
                                    user_id=user_id,
                                    remark='0',
                                    created_at=current_time,
                                    updated_at=current_time)
    # real_stock_record.version += 1
    # real_stock_record.real_stock -= amount
    # real_stock_record.occupy_stock -= occupy_amount
    # if real_stock_record.occupy_stock < 0:
    #     real_stock_record.occupy_stock = 0


    updates = 0
    # updates = db.session.query(Realstock).filter_by(id=real_stock_record.id, version=real_stock_record.version).update({
    #                 Realstock.version: real_stock_record.version + 1,
    #                 Realstock.real_stock: real_stock_record.real_stock - amount,
    #                 Realstock.occupy_stock: occupy_stock})
    if updates <= 0:
        from ...tasks.stock_update_task import stock_out_task
        stock_out_task.delay(kw)
        raise Exception("_DTC_%s_<biz_type:%s>, 更新失败：版本号不一致<version=%r>" % (
            real_stock_record.sku_id, business_type, real_stock_record.version))

    db.session.add(new_detail_record)
    db.session.commit()


@with_session
def stock_in(kw):
    """
    @desc: 入库逻辑，增加实物库存
    @param order_id: 订单号, 必要, 字符串
    @param warehouse_id: 仓库ID, 必要, 字符串
    @param warehouse_name: 仓库名称, 可选, 字符串
    @param sku_id: 商品编号, 必要, 字符串
    @param status_id: 商品状态类型，必要, 正整数
    @param amount: 数量，必要，正整数
    @param user_id: 操作用户，必要，字符串
    @param business_no: 业务流水号，必要，字符串
    @param business_type: 业务类型，必要，正整数
    @param order_type: 订单类型，必要，正整数
    """
    current_app.logger.info("stock_in kwargs: {}".format(kw))
    current_time = time.strftime("%Y-%m-%d %H:%M:%S")
    order_id = str(kw["order_id"])
    user_id = kw["user_id"]
    sku_id = kw["sku_id"]
    status_id = kw.get('status_id', 1)
    amount = abs(kw.get('amount', 0))
    warehouse_id = kw.get('warehouse_id')
    business_no = kw.get('business_no')
    # business_no = uuid4().hex
    business_type = kw.get('business_type')
    order_type = kw.get('order_type')

    wh = db.session.query(StockWarehouse).filter_by(warehouse_id=warehouse_id).first()
    goods = db.session.query(StockGood).filter_by(sku_id=sku_id).first()
    if not goods:
        raise Exception("商品表不存在商品{}".format(sku_id))
    # db.session.query(StockGood).with_for_update().filter_by(id=goods.id)
    real_stock_record = db.session.query(Realstock).filter_by(sku_id=sku_id,
                                                              warehouse_id=warehouse_id, status_id=status_id).first()
    task_id = "%s%s%s" % (sku_id, warehouse_id, status_id)
    if not real_stock_record:

        Realstock.new_record(warehouse_id, sku_id, status_id, 0, 0)
        # stock_redis.locker.new_release(task_id)
        real_stock_record = db.session.query(Realstock)\
            .filter_by(sku_id=sku_id, warehouse_id=warehouse_id, status_id=status_id).first()
    # db.session.query(Realstock).with_for_update().filter_by(id=real_stock_record.id)
    check_committed(business_no)

    new_detail_record = Stockdetail(operation_time=current_time,
                                    warehouse_id=warehouse_id,
                                    warehouse_name=wh.warehouse_name,
                                    business_type=business_type,
                                    order_type=order_type,
                                    business_no=business_no,
                                    wms_seq=business_no,
                                    order_id=order_id,
                                    status_id=status_id,
                                    sku_id=sku_id,
                                    amount=amount,
                                    original_real_stock=real_stock_record.real_stock,
                                    original_occupy_stock=real_stock_record.occupy_stock,
                                    real_stock_balance=real_stock_record.real_stock + amount,
                                    occupy_stock_balance=real_stock_record.occupy_stock,
                                    user_id=user_id,
                                    remark='0',
                                    created_at=current_time,
                                    updated_at=current_time)

    occupy_stock = 0 if real_stock_record.occupy_stock < 0 else real_stock_record.occupy_stock
    updates = db.session.query(Realstock).filter_by(id=real_stock_record.id, version=real_stock_record.version).update({
                    Realstock.version: real_stock_record.version + 1,
                    Realstock.real_stock: real_stock_record.real_stock + amount,
                    Realstock.occupy_stock: occupy_stock})
    if updates <= 0:
        from ...tasks.stock_update_task import stock_out_task
        stock_out_task.delay(kw)
        raise Exception("_DTC_%s_<biz_type:%s>, 更新失败：版本号不一致<version=%r>" % (
            real_stock_record.sku_id, business_type, real_stock_record.version))
    # real_stock_record.real_stock += amount
    # if real_stock_record.occupy_stock < 0:
    #     real_stock_record.occupy_stock = 0
    # db.session.add(real_stock_record)
    # sync_all_sale_stock([sku_id])

    db.session.add(new_detail_record)
    db.session.commit()


@with_session
def cancel_stock_occupy(kw):
    """
    @desc: 销售出库接口，同时扣减实物库存和占用库存
    @param order_id: 订单号, 必要, 字符串
    @param warehouse_id: 仓库ID, 必要, 字符串
    @param warehouse_name: 仓库名称, 可选, 字符串
    @param sku_id: 商品编号, 必要, 字符串
    @param status_id: 商品状态类型，必要, 正整数
    @param amount: 数量，必要，正整数
    @param user_id: 操作用户，必要，字符串
    @param business_no: 业务流水号，必要，字符串
    @param business_type: 业务类型，必要，正整数
    @param order_type: 订单类型，必要，正整数
    """
    current_time = time.strftime("%Y-%m-%d %H:%M:%S")
    order_id = str(kw["order_id"])
    source_order = kw.get('source_order')
    user_id = kw["user_id"]
    sku_id = kw["sku_id"]
    status_id = kw.get('status_id', 1)
    amount = abs(kw.get('amount', 0))
    warehouse_id = kw.get('warehouse_id')
    business_no = kw.get('business_no')
    # business_no = uuid4().hex
    business_type = kw.get('business_type', 3)
    order_type = kw.get('order_type', 3)

    wh = db.session.query(StockWarehouse).filter_by(warehouse_id=warehouse_id).first()
    real_stock_record = db.session.query(Realstock).filter_by(sku_id=sku_id,
                                                              status_id=status_id, warehouse_id=warehouse_id).first()

    if not real_stock_record:
        raise Exception("实物库存表仓库{}不存在商品{}记录".format(warehouse_id, sku_id))
    # db.session.query(Realstock).with_for_update().filter_by(id=real_stock_record.id)
    check_committed(business_no)

    goods = db.session.query(StockGood).filter_by(sku_id=sku_id).first()
    if not goods:
        raise Exception("商品表不存在商品{}".format(sku_id))
    original_occupy_record = db.session.query(Stockdetail).filter_by(order_id=order_id,
                                                                     sku_id=sku_id,
                                                                     warehouse_id=warehouse_id,
                                                                     status_id=status_id,
                                                                     order_type=13,
                                                                     remark='1').first()
    if not original_occupy_record:
        return
    # OccupyOrderSkuMapping.reset_state(original_occupy_record.order_id,
    #                                   original_occupy_record.sku_id)
    original_occupy_record.remark = '0'
    original_occupy_record.updated_at = current_time
    db.session.add(original_occupy_record)
    occupy_amount = original_occupy_record.amount
    new_detail_record = Stockdetail(operation_time=current_time,
                                    warehouse_id=warehouse_id,
                                    warehouse_name=wh.warehouse_name,
                                    business_type=business_type,
                                    order_type=order_type,
                                    business_no=business_no,
                                    order_id=order_id,
                                    status_id=status_id,
                                    sku_id=sku_id,
                                    amount=-amount,
                                    original_real_stock=real_stock_record.real_stock,
                                    original_occupy_stock=real_stock_record.occupy_stock,
                                    real_stock_balance=real_stock_record.real_stock,
                                    occupy_stock_balance=real_stock_record.occupy_stock - occupy_amount,
                                    user_id=user_id,
                                    remark='0',
                                    created_at=current_time,
                                    updated_at=current_time)

    occupy_stock = 0 if real_stock_record.occupy_stock < 0 else \
        real_stock_record.occupy_stock - occupy_amount

    updates = db.session.query(Realstock).filter_by(id=real_stock_record.id, version=real_stock_record.version).update({
                    Realstock.version: real_stock_record.version + 1,
                    Realstock.occupy_stock: occupy_stock})
    if updates <= 0:
        from ...tasks.stock_update_task import stock_out_task
        stock_out_task.delay(kw)
        raise Exception("_DTC_%s_<biz_type:%s>, 更新失败：版本号不一致<version=%r>" % (
            real_stock_record.sku_id, business_type, real_stock_record.version))

    # real_stock_record.occupy_stock -= occupy_amount
    # if real_stock_record.occupy_stock < 0:
    #     real_stock_record.occupy_stock = 0
    # if source_order:
    #     stock_unregist_task.delay(sku_id, source_order)
    # db.session.add(real_stock_record)
    db.session.add(new_detail_record)
    db.session.commit()

@with_session
def syncSkuFromPDC(kw):
    """
    @desc: 接收PDC 商品数据接口
    @param sku_id: skuCode 必要，字符串
    @param goods_name: fullName, 必要, 字符串
    @param category_id: 分类ID, 可选, 默认0
    @param is_set_scale: 是否设置售卖, 可选, 默认0
    @param status_id: 商品状态类型，可选, 默认0
    @param is_rx: drugSafetyClass = 1 是否处方药，可选必要，正整数
    @param is_otc: drugSafetyClass = 2 是否非处方药，可选必要，字符串
    @param common_name: 通用名称，必要，字符串
    @param specification: packageSpec 包装规格，必要，字符串
    @param manufacturer: 生产厂家，必要，字符串
    """

    sync_at = time.strftime("%Y-%m-%d %H:%M:%S")
    sku_id = kw.get("pdcCode")
    goods_name = kw.get('fullName')
    is_set_scale = 0
    status_id = 0
    category_id = 0
    drugSafetyClass = kw.get('drugSafetyClass')
    is_rx = 0
    is_otc = 0
    if drugSafetyClass == 1:
        is_rx = 1
    else:
        is_otc = 1
    common_name = kw.get('commonName')
    specification = kw.get('packageSpec')
    manufacturer = kw.get('manufacturer')

    # 校验参数
    isParamError = sku_id == '' or goods_name == '' or (is_rx == 0 and is_otc == 0) or common_name == ''
    if isParamError:
        return 220, '参数错误：sku_id【{}】,goods_name【{}】,drugSafetyClass【{}】，common_name【{}】，specification-packageSpec【{}】，' \
                                'manufacturer【{}】'.format(sku_id, goods_name, drugSafetyClass, common_name, specification, manufacturer)

    goods = db.session.query(StockGood).filter_by(sku_id=sku_id).first()
    if not goods:
        # 新增
        goods = StockGood()
        goods.created_at = sync_at
    goods.sku_id = sku_id
    goods.goods_name = goods_name
    goods.is_set_scale = is_set_scale
    goods.status_id = status_id
    goods.category_id = category_id
    goods.is_rx = is_rx
    goods.is_otc = is_otc
    goods.common_name = common_name
    goods.specification = specification and [specification] or '无'
    goods.manufacturer = manufacturer and [manufacturer] or '无'
    goods.sync_at = sync_at
    goods.updated_at = sync_at

    # real_stock_record.occupy_stock -= occupy_amount
    # if real_stock_record.occupy_stock < 0:
    #     real_stock_record.occupy_stock = 0
    # if source_order:
    #     stock_unregist_task.delay(sku_id, source_order)
    # db.session.add(real_stock_record)
    db.session.add(goods)
    db.session.commit()
    return 200, 'success'
